package com.william.jdbcplus.core.dialect.fill.impl;

import cn.hutool.core.util.NumberUtil;
import com.william.jdbcplus.common.entity.Entity;
import com.william.jdbcplus.core.crud.CrudConfig;
import com.william.jdbcplus.core.crud.impl.ShardCrud;
import com.william.jdbcplus.core.dialect.fill.IFill;
import com.william.jdbcplus.core.toolkit.StringPool;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.integration.redis.util.RedisLockRegistry;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.Lock;

/**
 * 日期加数字填充
 * <p>
 * yyyyMMdd + 10位数字自增
 * </p>
 *
 * @author william
 */
public class AutomicFill implements IFill {
    private static final String placeholder = "00000000000";

    private static final String redisKeyField = "AtomicField";

    /**
     * 获取redis主键
     *
     * @param entityClass
     * @param config
     * @param <M>
     * @return
     */
    private <M extends Entity> String getRedisKey(Class<M> entityClass, String fieldName, CrudConfig config) {
        String redisPrimaryKey = redisKeyField + StringPool.DOT + entityClass.getName() + StringPool.DOT + fieldName + StringPool.DOT + config.getDsURL();
        return redisPrimaryKey;
    }


    @Override
    public <M extends Entity> Object getValue(Class<M> entityClass, String fieldName, CrudConfig config) {
        String redisPrimaryKey = getRedisKey(entityClass, fieldName, config);
        Long result = null;

        RedisLockRegistry redisLock = config.getRedisLock();
        Lock lock = redisLock.obtain(redisPrimaryKey);

        try {
            lock.lockInterruptibly();

            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            Date date = new Date();
            String dataToday = sdf.format(date);
            RedisAtomicLong counter = new RedisAtomicLong(redisPrimaryKey, config.getRedisTemplate().getConnectionFactory());
            if (counter.get() == 0) {
                Long maxId = ShardCrud.getInstance().queryMaxId(entityClass, config);
                if (maxId != null && maxId.toString().length() == placeholder.length() + 8) {
                    String maxStr = maxId.toString().substring(8);
                    if (NumberUtil.isNumber(maxStr)) {
                        counter.set(Long.parseLong(maxStr));
                    }
                }
            }
            Long pkMax = counter.incrementAndGet();
            String bigPart = dataToday + placeholder;
            result = Long.parseLong(bigPart) + pkMax;
        } catch (Exception ex) {

        } finally {
            lock.unlock();
        }

        return result;
    }

    @Override
    public <M extends Entity> List<?> getValueList(Class<M> entityClass, String fieldName, int count, CrudConfig config) {
        String redisPrimaryKey = getRedisKey(entityClass, fieldName, config);
        List<Long> result = new ArrayList<>();

        RedisLockRegistry redisLock = config.getRedisLock();
        Lock lock = redisLock.obtain(redisPrimaryKey);

        try {
            lock.lockInterruptibly();

            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            Date date = new Date();
            String dataToday = sdf.format(date);
            RedisAtomicLong counter = new RedisAtomicLong(redisPrimaryKey, config.getRedisTemplate().getConnectionFactory());
            if (counter.get() == 0) {
                Long maxId = ShardCrud.getInstance().queryMaxId(entityClass, config);
                if (maxId != null && maxId.toString().length() == placeholder.length() + 8) {
                    String maxStr = maxId.toString().substring(8);
                    if (NumberUtil.isNumber(maxStr)) {
                        counter.set(Long.parseLong(maxStr));
                    }
                }
            }
            Long bigPart = Long.parseLong(dataToday + placeholder);
            if (count > 0) {
                Long pkMax = counter.get();
                counter.set(pkMax + count);
                for (int i = 1; i <= count; i++) {
                    result.add(bigPart + pkMax + i);
                }
            }
        } catch (Exception ex) {

        } finally {
            lock.unlock();
        }

        return result;
    }

    //现在到今天结束的毫秒数
    public static Long getCurrent2TodayEndMillisTime() {
        Calendar todayEnd = Calendar.getInstance();
        // Calendar.HOUR 12小时制
        // HOUR_OF_DAY 24小时制
        todayEnd.set(Calendar.HOUR_OF_DAY, 23);
        todayEnd.set(Calendar.MINUTE, 59);
        todayEnd.set(Calendar.SECOND, 59);
        todayEnd.set(Calendar.MILLISECOND, 999);
        return todayEnd.getTimeInMillis() - System.currentTimeMillis() + 10000;
    }

    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date date = new Date();
        String dataToday = sdf.format(date);
        long pkMax = 9588885554L;
        String bigPart = dataToday + placeholder;
        long result = Long.parseLong(bigPart) + pkMax;
        long result2 = Long.parseLong("00000000000");
        System.out.println(result);
        System.out.println(result2);
        System.out.println(NumberUtil.isNumber("00000000000"));
    }
}
